package com.hup.utils.swing.customView;

import lombok.Getter;
import lombok.Setter;
import sun.swing.DefaultLookup;

import javax.swing.*;
import javax.swing.border.Border;
import javax.swing.border.EmptyBorder;
import java.awt.*;
import java.util.Collection;
import java.util.Vector;

/**
 * 改进的ComboBox,提供了ItemTextHandler
 *
 * @author hugan
 * @date 2020/10/20
 */
public class HComboBox<E> extends JComboBox<E> {
    private static final Border SAFE_NO_FOCUS_BORDER = new EmptyBorder(1, 1, 1, 1);
    private static final Border DEFAULT_NO_FOCUS_BORDER = new EmptyBorder(1, 1, 1, 1);

    @Setter
    @Getter
    private ItemTextHandler<E> itemTextHandler;

    public HComboBox() {
        setRenderer(new TypedComboBoxRender());
    }

    public void setModel(E[] items) {
        setModel(new DefaultComboBoxModel<>(items));
    }

    public void setModel(Vector<E> v) {
        setModel(new DefaultComboBoxModel<>(v));
    }

    public void setModel(Collection<E> v) {
        setModel(new DefaultComboBoxModel<>(new Vector<>(v)));
    }

    @SuppressWarnings("unchecked")
    @Override
    public E getSelectedItem() {
        return (E) super.getSelectedItem();
    }

    private class TypedComboBoxRender extends DefaultListCellRenderer {

        private Border getNoFocusBorder() {
            Border border = DefaultLookup.getBorder(this, ui, "List.cellNoFocusBorder");
            if (System.getSecurityManager() != null) {
                if (border != null) return border;
                return SAFE_NO_FOCUS_BORDER;
            } else {
                if (border != null &&
                        (noFocusBorder == null ||
                                noFocusBorder == DEFAULT_NO_FOCUS_BORDER)) {
                    return border;
                }
                return noFocusBorder;
            }
        }

        @SuppressWarnings("unchecked")
        @Override
        public Component getListCellRendererComponent(JList<?> list, Object value, int index, boolean isSelected,
                boolean cellHasFocus) {
            setComponentOrientation(list.getComponentOrientation());

            Color bg = null;
            Color fg = null;

            JList.DropLocation dropLocation = list.getDropLocation();
            if (dropLocation != null
                    && !dropLocation.isInsert()
                    && dropLocation.getIndex() == index) {

                bg = DefaultLookup.getColor(this, ui, "List.dropCellBackground");
                fg = DefaultLookup.getColor(this, ui, "List.dropCellForeground");

                isSelected = true;
            }

            if (isSelected) {
                setBackground(bg == null ? list.getSelectionBackground() : bg);
                setForeground(fg == null ? list.getSelectionForeground() : fg);
            } else {
                setBackground(list.getBackground());
                setForeground(list.getForeground());
            }

            if (value instanceof Icon) {
                setIcon((Icon) value);
                setText("");
            } else {
                setIcon(null);
                if (itemTextHandler == null) {
                    setText((value == null) ? "" : value.toString());
                } else {
                    setText(value == null ? "" : itemTextHandler.getText((E) value));
                }
            }

            setEnabled(list.isEnabled());
            setFont(list.getFont());

            Border border = null;
            if (cellHasFocus) {
                if (isSelected) {
                    border = DefaultLookup.getBorder(this, ui, "List.focusSelectedCellHighlightBorder");
                }
                if (border == null) {
                    border = DefaultLookup.getBorder(this, ui, "List.focusCellHighlightBorder");
                }
            } else {
                border = getNoFocusBorder();
            }
            setBorder(border);
            return this;
        }

        private String getText(E value) {
            return null;
        }

    }

    public interface ItemTextHandler<T> {
        /**
         * @param value notNull
         */
        String getText(T value);
    }
}
